package main

import (
	"context"
	"encoding/json"

	"log"
	"net/http"
)

/*
golang http 发送请求处理
参考: todo https://studygolang.com/articles/4489
*/

func httpDo(ctx context.Context, req *http.Request, f func(*http.Response, error) error) error {
	tr := &http.Transport{}
	client := &http.Client{Transport: tr}
	c := make(chan error, 1)
	go func() {
		c <- f(client.Do(req))
	}()
	select {
	case <-ctx.Done():
		tr.CancelRequest(req)
		<-c // Wait for f to return.
		return ctx.Err()
	case err := <-c:
		return err
	}
}

type Result struct {
	Title string
	URL   string
}
type Results []Result

func hello(req *http.Request) (Results, error) {
	ctx, _ := context.WithCancel(context.Background())
	var results Results
	err := httpDo(ctx, req, func(resp *http.Response, err error) error {
		if err != nil {
			return err
		}
		//log.Println("==================")
		//bodyBytes, _ := ioutil.ReadAll(resp.Body)
		//log.Println(string(bodyBytes))
		//log.Println("==================")

		defer resp.Body.Close()
		//Parse the JSON search result.
		//https://developers.google.com/web-search/docs/#fonje
		var data struct {
			ResponseData struct {
				Results []struct {
					TitleNoFormatting string `json:"title_no_formatting"`
					URL               string `json:"url"`
				}
			}
		}
		// 手动丢弃读取完毕的数据
		//_, err = io.Copy(ioutil.Discard, resp.Body)

		//if err := json.NewDecoder(strings.NewReader(string(bodyBytes))).Decode(&data);err!=nil {
		//if err := json.NewDecoder(strings.NewReader(j)).Decode(&data);err!=nil {
		if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
			return err
		}
		for _, res := range data.ResponseData.Results {
			results = append(results, Result{Title: res.TitleNoFormatting, URL: res.URL})
		}
		return nil
	})
	return results, err
}

func main() {
	url := "http://127.0.0.1:8000/json.php"
	req, _ := http.NewRequest("GET", url, nil)
	result, err := hello(req)
	if err != nil {
		log.Fatal(err)
	}
	log.Println(result)
}
